In the previous topics, we have explored ways to produce various type
of graphs. However all of them (with the exception of
mapview) are static. In this topic, we will discuss some
methods that can be used to make visuals produced using R and ggplot2 to
be interactive by introducing hover effect, tooltip, and click effect.
Interactive visuals are great if you want to publish your visual in a
website or blog, and readers can interact with the visuals, giving them
more information when hovering and making the visuals more
attractive.
As usual we load the important packages.
One of the most popular libraries for interactive visualization in R is Plotly, which provides dynamic and customizable plots with ease. Unlike static visualizations, interactive plots allow users to hover over data points, zoom in and out, and filter data dynamically.
To use Plotly in R, you need to install the plotly
package if you haven’t already:
Then, load the package:
Plotly in R works well with ggplot2, but it also allows users to
create interactive plots from scratch using the plot_ly()
function. If you want to use ggplot2, you can save the ggplot graph as
an object and use ggplotly() function to convert it to
Plotly graph.
Let’s create an interactive scatter plot using the mpg
data set from ggplot2 package:
# Save the ggplot object as a variable
p <- ggplot(data = mpg, mapping=aes(x=displ, y=hwy, color=class)) +
geom_point(alpha=0.75) +
theme_minimal() +
labs(x = "Engine displacement (L)",
y = "Highway miles per gallon",
color = "Vehicle type")
# Convert the ggplot object to plotly
ggplotly(p)Notice that when you hover your mouse over the points, the mapping
(x, y, color) of the points are
shown in a tooltip. Notice also that on the top-right of the graph,
there are some buttons you can click to download the plot as PNG, zoom
in and out, and so on. Additionally, try clicking on a vehicle type in
the legend to hide/show related points. You can also double click on a
vehicle type in the legend to show data for that category only.
The tooltip can be customized using the text mapping in
the aes() function, and using the tooltip
argument in the ggplotly(). In the code below, the
<br> is used to break the line using HTML format.
p <- ggplot(data = mpg, mapping=aes(x=displ, y=hwy, color=class,
text=paste('Engine displacement:', displ,
'<br>Highway mpg:', hwy,
'<br>Vehicle type:', class))) +
geom_point(alpha=0.75) +
theme_minimal() +
labs(x = "Engine displacement (L)",
y = "Highway miles per gallon",
color = "Vehicle type")
ggplotly(p, tooltip="text")Alternatively, if we do not want to use ggplotly(), we
can simply use the plot_ly() function to create a Plotly
graph.
# Create a scatter plot
fig <- plot_ly(data = mpg,
x = ~displ,
y = ~hwy,
type = 'scatter',
marker = list(size = 10, color = 'blue'))
# Display the plot
fig In this example, type = 'scatter' specifies a scatter
plot, and the marker argument customizes point size and
color.
Here is another example with interactive line plot using the
economics data set from ggplot2.
p <- ggplot(data = economics, mapping = aes(x=date, y=unemploy)) +
geom_line(color="red") +
theme_minimal() +
labs(x="Date", y="Unemployment (thousands)")
ggplotly(p)By default, the hover label appears at the nearest point in the
chart. But for a line chart, you can change the hover mode so that it
follows the x-axis for multiple graphs. This can be done by saving the
Plotly object to a variable and using hovermode="x" in the
layout function.
library(dslabs)
# Filter the data for Malaysia and Singapore only
regional_data <- filter(gapminder, country %in% c("Malaysia","Singapore"))
# Save the ggplot object to a variable
p <- ggplot(data=regional_data, mapping=aes(x=year, y=fertility, color=country)) +
geom_line() +
theme_minimal()
# Convert the ggplot object to plotly
p2 <- ggplotly(p)
# Change the plotly layput so that mouse hover follows x-axis
layout(p2, hovermode="x")Since Plotly works with ggplot2, the interactivity also works when facetting. In the output below, a tooltip appear when you hover your mouse over points. Then, if you zoom-in, both the left and right facets will be zoomed it at the same region.
mpg2 <- mpg %>%
mutate(trans=ifelse(substring(trans,1,1) == "a", "auto", "manual"))
p <- ggplot(data = mpg2, mapping = aes(x=displ, y=hwy, color=class)) +
geom_point(alpha=0.75) +
facet_wrap(~trans)+
labs(x = "Engine displacement (L)",
y = "Highway miles per gallon",
color = "Vehicle type")
ggplotly(p)ggiraph PackageAnother useful package in R is the ggiraph package which
extends the widely used ggplot2 package by enabling
interactivity in an easy-to-use framework. ggiraph
essentially wraps your ggplot2 objects, injecting
JavaScript code that enables features like tooltips, hover effects, and
click actions.
Before diving into examples, ensure you have installed the
ggiraph package:
Then, load it into your R session:
The ggiraph package builds upon ggplot2 by
adding interactive features through the geom_ functions.
These enhanced geoms allow users to incorporate tooltips, hyperlinks,
and hover effects seamlessly.
ggiraphThe core principle involves adding aesthetic mappings related to
interactivity. These mappings, like tooltip and
onclick, are then translated into interactive behavior by
ggiraph.
To use ggiraph with ggplot2 for interactive
plots, we first use ggplot() function to specify the data
and mapping. Then, when calling the geom function, we need
to add _interactive at the end of the function name. Save
the ggplot object to a variable, and use the girafe()
function with the argument ggobj equal to the ggplot
object.
Consider a simple scatter plot:
# Save the ggplot object
p <- ggplot(data=mpg, mapping=aes(x=displ, y=hwy, color=class,
tooltip=manufacturer)) +
# Use interactive version of geom_point
geom_point_interactive() +
theme_minimal()
# Create interactive graphic using ggplot object
girafe(ggobj = p,
options = list(opts_sizing(rescale = FALSE)))In the example above,
geom_point_interactive() is used instead of
geom_point(), allowing for tooltip interactions.
The tooltip aesthetic is mapped to
manufacturer, showing the car’s manufacturer when hovering
over a point.
ggiraph() renders the ggplot object as an
interactive graphic. The options argument is included for
sizing the plot in HTML page for readability.
When you move your mouse or cursor to a point, notice that a tooltip appears that shows you the manufacturer’s name.
Similar to Plotly, we can modify the tooltip option in
the mapping using HTML code if we want to customize it. Note that in the
code below, another options is added to the girafe()
function to change the background color of the tooltip.
We can enhance this plot by adding hover effects, such as changing
the point’s size and color. But this require adding the
data_id option in the aes() mapping.The
css argument in the opts_hover() function can
be used to modify the effect (color, size, etc) using CSS format.
Additionally, we can add hover_nearest = TRUE in the
interactive geom_ function, which applies the hover effect
to the nearest point/element of the mouse, even if the mouse is not
exactly on the point. The nearest_distance argument in
opts_hover() controls the distance for the hover effect to
take place, if hover_nearest = TRUE is used.
# Save ggplot object
p <- ggplot(data=mpg, mapping=aes(x=displ, y=hwy, color=class,
tooltip=manufacturer, data_id=manufacturer)) +
# Use interactive geom_point
# Make the mouse hover interacts with the nearest point
geom_point_interactive(hover_nearest = TRUE) +
theme_minimal()
girafe(ggobj = p,
# Change the CSS style of points to 5px and red when hovered
options = list(opts_hover(css = "r:5px;fill:red;",
nearest_distance = 20),
opts_sizing(rescale = FALSE)))Notice that when your mouse or cursor hovers close to a point, the
point together with other points with similar manufacturer are
highlighted in red and bigger size. Here, opts_hover
changes the radius (r) and fill color of the points when
the mouse hovers over them. The data_id mapping is
important to tell ggiraph to identify the points.
You can also add hyperlinks to points, making them clickable. Here’s an example where each point links to a Google search for the respective car manufacturer.
p <- ggplot(data=mpg, mapping=aes(x=displ, y=hwy, color=class,
tooltip=manufacturer, data_id=manufacturer,
)) +
# Specify onlick behaviour to open new windows for google search
geom_point_interactive(mapping=aes(
onclick = paste0('window.open("https://www.google.com/search?q=',
manufacturer, '")'))) +
theme_minimal()
girafe(ggobj = p,
options = list(opts_hover(css = "r:5px;fill:red;"),
opts_sizing(rescale = FALSE)))patchwork with ggiraphThe ggiraph also works with facet by highlighting points
with similar data_id. Notice in the visual below, when
hovering a point, all the points with the same vehicle class type on the
left and right facets appear bigger as specified in
opts_hover() function.
mpg2 <- mpg %>%
mutate(trans=ifelse(substring(trans,1,1) == "a", "auto", "manual"))
p <- ggplot(data = mpg2, mapping = aes(x=displ, y=hwy, color=class,
tooltip=class,
data_id=class)) +
geom_point_interactive(alpha=0.75) +
facet_wrap(~trans)+
labs(x = "Engine displacement (L)",
y = "Highway miles per gallon",
color = "Vehicle type")
girafe(ggobj = p,
options = list(opts_hover(css = "r:5px;"),
opts_tooltip(use_fill = TRUE),
opts_sizing(rescale = FALSE)))We have talked about using the patchwork package to
combine multiple graphs into one plot. One good thing about
ggiraph is that it allows for interaction with
patchwork by linking the multiple graphs using the
data_id mapping.
In the code below, we use the gapminder data set from
the gapminder package to create two graphs. Both graphs
have the same data_id mapping, which is the name of the
country. When hovering a bar on either graph, the corresponding bar with
the same data_id is highlighted in the other graph.
library(patchwork)
library(gapminder)
df1 <- filter(gapminder, year == 1997 & continent=="Asia")
df2 <- filter(gapminder, year == 2007 & continent=="Asia")
p1 <- ggplot(data=df1, mapping=aes(x=lifeExp, y=reorder(country,lifeExp),
tooltip=lifeExp,
data_id=country)) +
geom_bar_interactive(stat="identity", fill="steelblue") +
labs(x="1997", y="Country")
p2 <- ggplot(data=df2, mapping=aes(x=lifeExp, y=reorder(country,lifeExp),
tooltip=lifeExp,
data_id=country)) +
geom_bar_interactive(stat="identity", fill="steelblue") +
labs(x="2007", y="")
p <- p1+p2 &
theme_minimal() &
theme(panel.grid.major.y = element_blank())
girafe(code = print(p), options = list(opts_sizing(rescale = FALSE)))DT packageData visualization is a crucial part of data analysis, but sometimes
a well-structured, interactive table is just as powerful as a graph. The
DT package in R provides an elegant way to transform static
tables into dynamic, user-friendly displays, making it easier to explore
and analyze data.
The DT package is an interface to the JavaScript
DataTables (https://datatables.net/) library. It allows users to
create tables with interactive features such as searching, sorting,
filtering, and pagination, all within an R environment. The
DT package is particularly useful when working with large
datasets, as it enhances accessibility and usability without requiring
external software.
First, ensure you have the package installed:
Then, load the package.
Once the necessary packages are loaded, creating an interactive table
is straightforward. Use the datatable() function from
DT:
This command generates an interactive table where users can:
Search for specific values.
Sort columns in ascending or descending order.
Paginate through the rows for easy navigation.
For better data exploration, you can enable column-specific filtering and row highlighting:
{r} datatable(gapminder, filter = "top", rownames = FALSE)}
The filter = "top" argument adds a filter box to each
column, allowing users to refine their search dynamically.
The DT package allows for extensive customization. You
can modify the table layout, set the number of rows displayed by
default, enable or disable sorting, and even add export options. Below
is an example with customized options:
datatable(gapminder,
caption = "Countries demographic data from the gapminder data set",
options = list(pageLength = 10,
autoWidth = TRUE,
dom = 'Bfrtip',
buttons = c('copy', 'csv', 'excel', 'pdf', 'print')),
extensions = 'Buttons')In the code above:
The dom = 'Brftip' in the options
specify the elements we want in the table, which are
Buttons, filtering input (the search filter),
processing indicator (to show when table is being processed
for example when sorting), table, table
information summary (e.g. ‘Showing 1 to …’), and
pagination control. For more info on this, you can check
the dom section in the DataTables manual (https://datatables.net/reference/option/dom).
The default number of displayed rows is set to 10 using the
pageLength = 10 line in the options.
Automatic column width adjustments is enabled using
autoWidth = TRUE.
Export buttons for copying and saving the table in different
formats (CSV, Excel, PDF, etc.) are added using the buttons
argument in the options and
extensions = 'Buttons' argument.
The htmlwidgets package serves as a crucial bridge
between R and JavaScript libraries, enabling the creation of interactive
web visualizations. A core function of this package is
saveWidget(), which provides a straightforward way to save
these interactive charts as standalone HTML files. This is essential for
sharing and embedding interactive visualizations created with packages
like plotly, ggiraph, and DT.
The saveWidget() function takes two primary arguments:
the interactive widget object (e.g., a plotly plot, a
girafe graphic, or a DT table) and the desired
filename for the HTML output.
library(htmlwidgets)
# Example using a plotly chart
library(plotly)
p1 <- ggplot(data = mpg, mapping=aes(x=displ, y=hwy, color=class,
text=paste('Engine displacement:', displ,
'<br>Highway mpg:', hwy,
'<br>Vehicle type:', class))) +
geom_point(alpha=0.75) +
theme_minimal() +
labs(x = "Engine displacement (L)",
y = "Highway miles per gallon",
color = "Vehicle type")
p <- ggplotly(p1, tooltip="text")
# Save the visual as mpg_plotly.html
saveWidget(p, "mpg_plotly.html")# Example using a ggiraph graphic
library(patchwork)
library(gapminder)
df1 <- filter(gapminder, year == 1997 & continent=="Asia")
df2 <- filter(gapminder, year == 2007 & continent=="Asia")
p1 <- ggplot(data=df1, mapping=aes(x=lifeExp, y=reorder(country,lifeExp),
tooltip=lifeExp,
data_id=country)) +
geom_bar_interactive(stat="identity", fill="steelblue") +
labs(x="1997", y="Country")
p2 <- ggplot(data=df2, mapping=aes(x=lifeExp, y=reorder(country,lifeExp),
tooltip=lifeExp,
data_id=country)) +
geom_bar_interactive(stat="identity", fill="steelblue") +
labs(x="2007", y="")
p3 <- p1+p2 &
theme_minimal() &
theme(panel.grid.major.y = element_blank())
p <- girafe(code = print(p3), options = list(opts_sizing(rescale = FALSE)))
# Save the visual as gapminder_girafe.html
saveWidget(p, "gapminder_girafe.html")# Example using a DT table
library(DT)
table <- datatable(gapminder[, c("country", "year", "lifeExp", "gdpPercap")],
filter = "top",
options = list(pageLength = 5))
# Save the table as gapminder_table.html
saveWidget(table, "gapminder_table.html")The HTML file will be saved in your working directory. You can then share the files via email, upload to a website, or embed them within a blog post or web application.
This topic delves deep on creating interactive visualizations using R
and several packages including plotly,
ggiraph, and DT. Note that there are other
packages you can use to make interactive graphs in R such as
rbokeh, rCharts, highcharter, or
dygraphs. You are free to read and explore on these other
methods. After creating the interactive charts, you can save it to a
HTML file to share or use it on a website.